/**
 * 下面的封装是参考了下面的例子实现
 * https://github.com/liuxinwu/vite-request
 */
import { ElMessage } from 'element-plus'
import { customConfigDefault } from './config'
import { Instance } from './instance'
import {
  transfromPath,
  removeIdentifierFromStart,
  addIdentifierToEnd,
  handleRepeat,
  createError,
  getErrorInfo
} from './utils'
import {
  handleAfterRequest,
  handleBeforeRequest,
  handleErrorReuqest,
  handleSuccessRequest,
  cache
} from './utils/handleRequest'

// 标识符
const IDENTIFIER = '/'

class Request {
  customConfigDefault = customConfigDefault

  /**
   * 构造函数，进行初始化操作
   * @param {object} config axios request config
   * @param {object} customConfig 自定义配置操作
   */
  constructor(config, customConfig) {
    // 格式化 baseURL
    if (config.baseURL) {
      config.baseURL = transfromPath(
        config.baseURL,
        IDENTIFIER,
        addIdentifierToEnd
      )
    }

    // 初始化 axios 实例
    this.instance = new Instance(config)

    // 合并自定义配置
    this.customConfigDefault = Object.assign(
      {},
      customConfigDefault,
      customConfig
    )
  }

  async request(config, customConfig) {
    const _customConfig = {
      ...this.customConfigDefault,
      ...customConfig
    }
    const baseUrl = this.instance.axiosInstance.defaults.baseURL ?? ''
    // 格式化 url
    if (config.url) {
      config.url = transfromPath(
        config.url,
        IDENTIFIER,
        removeIdentifierFromStart
      )
    }
    // 设置 requestKey
    const requestKey = `${window.location.href}_${baseUrl + config.url}_${
      config.method
    }`

    // 网络检查
    if (!window.navigator.onLine) {
      ElMessage({
        type: 'danger',
        duration: 1500,
        messasge: '网络不可用'
      })
      return Promise.reject(createError('网络不可用', config))
    }

    // 处理重复请求并记录
    if (handleRepeat(requestKey)) {
      return Promise.reject(createError('重复请求已被取消', config))
    }

    const handleRequest = async () => {
      const instance = this
      try {
        handleBeforeRequest({ config, _customConfig, requestKey })

        // 请求发起
        const res = await this.instance.axiosInstance.request(config)
        return handleSuccessRequest({
          instance,
          config,
          _customConfig,
          requestKey,
          res
        })
      } catch (error) {
        return handleErrorReuqest({
          error,
          config,
          customConfig,
          _customConfig,
          instance,
          requestKey
        })
      } finally {
        handleAfterRequest({ _customConfig, requestKey })
      }
    }
    if (_customConfig.isNeedCache) {
      try {
        const res = cache.getrequestKey()
        return res
      } catch (error) {
        return handleRequest()
      }
    } else {
      return handleRequest()
    }
  }

  async get(config, customConfig) {
    return this.request({ ...config, method: 'get' }, customConfig)
  }

  async post(config, customConfig) {
    return this.request({ ...config, method: 'post' }, customConfig)
  }

  async put(config, customConfig) {
    return this.request({ ...config, method: 'put' }, customConfig)
  }

  async delete(config, customConfig) {
    return this.request({ ...config, method: 'delete' }, customConfig)
  }

  getAllErrorInfo() {
    return getErrorInfo(this)
  }
}

export default new Request({
  baseURL: 'http://127.0.0.1:5000'
})
